﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MCSFramework.IFStrategy;
using MCSFramework.DBUtility;
using System.Data.SqlClient;
using System.Data;

namespace MCSFramework.SQLDAL
{
    public abstract class BaseSimpleDAL<T> : ISimpleDAL<T>
    {
        public string _ProcePrefix = "";

        /// <summary>
        /// 根据IDataReader的当前值来填充reader，在当前类中取数据的方法中使用----------------此处在实例中重载是因为DataReader需要填充的类公共属性名不同
        /// </summary>
        /// <param name="dr"></param>
        /// <returns></returns>
        protected abstract T FillModel(IDataReader dr);

        /// <summary>
        /// 获取数据库中对象实例的列表，用于GetModelList方法
        /// </summary>
        /// <param name="dr"></param>
        /// <returns></returns>
        private IList<T> FillModelList(IDataReader dr)
        {
            IList<T> list = new List<T>();
            while (dr.Read())
            {
                list.Add(FillModel(dr));
            }
            dr.Close();
            return list;
        }


        #region ISimpleDAL<T> 成员

        //virtual关键字允许 在派生类中修改（以override关键字标志）
        //当方法只使用了一个参数（方法体较为简单）时可在基类中实现，参数较多时以抽象方法形式在子类中实现（如该类的Update方法和Add方法）



        public virtual T GetModel(int id)
        {
            //创建输入参数
            SqlParameter[] parameters = { MCSFramework.DBUtility.SQLDatabase.MakeInParam(@"ID", SqlDbType.Int, 4, id) };
            SqlDataReader dr = null;
            //执行存储过程并输出到SqlDataReader 
            MCSFramework.DBUtility.SQLDatabase.RunProc(_ProcePrefix + "_GetModel", parameters, out dr);

            T m = default(T);
            if (dr.Read())
            {
                m = FillModel(dr);
            }
            dr.Close();
            return m;
        }

        /// <summary>
        /// 根据code获取Model。对GetModel方法进行重载，以通过数据表中的code值查询实体。因为并非每张表都存在code字段，所以并未在ISimpleDAL中列出
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual T GetModel(string code)
        {
            SqlParameter[] paramaters = { MCSFramework.DBUtility.SQLDatabase.MakeInParam("@Code", SqlDbType.VarChar, 50, code) };
            SqlDataReader dr = null;
            MCSFramework.DBUtility.SQLDatabase.RunProc(_ProcePrefix + "_GetModelByCode", paramaters, out dr);
            T m = default(T);
            if (dr.Read())
            {
                m = FillModel(dr);
            }
            return m;
        }

        /// <summary>
        /// 根据Guid类型的id重载GetModel方法，Guid类型的主键是为了在不同系统公用的数据表存储时不会出现重复id
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual T GetModel(Guid id)
        {
            SqlParameter[] paramaters = { MCSFramework.DBUtility.SQLDatabase.MakeInParam("@id", SqlDbType.UniqueIdentifier, 16, id) };
            SqlDataReader dr = null;
            MCSFramework.DBUtility.SQLDatabase.RunProc(_ProcePrefix + "_GetModel", paramaters, out dr);
            T m = default(T);
            if (dr.Read())
            {
                m = FillModel(dr);
            }
            return m;
        }

        /*
         参数较多的方法在子类中实现
         */

        /// <summary>
        /// Add作为抽象类时因为不同数据表Add的参数键值对不同，需在子类重写。
        /// </summary>
        /// <param name="m"></param>
        /// <returns></returns>
        public abstract int Add(T m);

        /// <summary>
        /// 将Model信息更新到数据库，作为抽象方法是因为不同的情况update语句也不同，需在子类中重写
        /// </summary>
        /// <param name="m"></param>
        /// <returns></returns>
        public abstract int Update(T m);


        /// <summary>
        /// 删除指定id的字段
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual int Delete(int id)
        {
            SqlParameter[] paramaters = { MCSFramework.DBUtility.SQLDatabase.MakeInParam("@ID", SqlDbType.Int, 4, id) };
            return MCSFramework.DBUtility.SQLDatabase.RunProc(_ProcePrefix + "_Delete", paramaters);
        }

        /// <summary>
        /// 重载Delete方法，删除指定的Guid类型的id记录
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual int Delete(Guid id)
        {
            SqlParameter[] paramaters = { MCSFramework.DBUtility.SQLDatabase.MakeInParam("@ID", SqlDbType.UniqueIdentifier, 16, id) };
            return MCSFramework.DBUtility.SQLDatabase.RunProc(_ProcePrefix + "_Delete", paramaters);
        }

        /// <summary>
        /// 查询指定id的字段在数据表中是否存在
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual bool Exists(int id)
        {
            SqlParameter[] parameters = { MCSFramework.DBUtility.SQLDatabase.MakeInParam(@"@ID", SqlDbType.Int, 4, id) };
            return MCSFramework.DBUtility.SQLDatabase.RunProc(_ProcePrefix + "_Exists", parameters) == 1;
        }

        public virtual bool Exists(Guid id)
        {
            SqlParameter[] parameters = { MCSFramework.DBUtility.SQLDatabase.MakeInParam(@"@ID", SqlDbType.UniqueIdentifier, 16, id) };
            return MCSFramework.DBUtility.SQLDatabase.RunProc(_ProcePrefix + "_Exists", parameters) == 1;
        }

        /// <summary>
        /// 根据自定义SQL条件获取Model列表的多个实例
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        public IList<T> GetModelList(string condition)
        {
            if (condition == null)
            {
                condition = "";
            }
            SqlParameter[] paramaters = { MCSFramework.DBUtility.SQLDatabase.MakeInParam(@"Condition", SqlDbType.VarChar, 2000, condition) };
            SqlDataReader dr = null;
            MCSFramework.DBUtility.SQLDatabase.RunProc(_ProcePrefix + "_GetByCondition", paramaters, out dr);

            return FillModelList(dr);
        }


        #endregion

        /// <summary>
        /// 将Model中的值赋到类集合
        /// </summary>
        /// <param name="m"></param>
        /// <returns></returns>
        protected virtual SqlParameterDictionary GetParameterDictionary(T m)
        {
            return new SqlParameterDictionary();
        }
    }
}
